<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>声音律动</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            background: url(./3.png) center;
            background-size: cover;
            backdrop-filter: blur(50px) grayscale(50%);
        }

        .music-box {
            position: relative;
            width: 400px;
            height: 400px;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .my-canvas {
            position: absolute;
            top: 0;
        }

        .my-music-btn {
            position: relative;
            width: 250px;
            height: 250px;
            background: url(./3.png);
            background-size: cover;
            border-radius: 50%;
            border: none;
            outline: none;
            animation: music-btn-anim 20s infinite linear;
        }

        .my-music-btn.rotate {
            animation-play-state: paused;
        }

        @keyframes music-btn-anim {
            from {
                transform: rotate(0deg);
            }

            to {
                transform: rotate(360deg);
            }
        }

        .toUpdata {
            top: 0;
            left: 0;
            position: fixed;
            width: 120px;
            height: 30px;
            /* background-color: #fff; */
            align-self: center;
            font-size: 18px;
            text-align: center;
            vertical-align: middle;
            color: rgb(250, 104, 42);
        }

        input {
            opacity: 0;
            filter: alpha(opacity=0);
            position: absolute;
            top: 0;
            left: 0;
            width: 120px;
            height: 30px;
            cursor: pointer;
            background-color: rgb(250, 104, 42);
            z-index: 10;
        }
    </style>
</head>

<body>
    <div class="toUpdata">
        点击上传音乐
        <input type="file" id="fileInput" value="选择音乐" accept="audio/mp3">
    </div>
    <div class="music-box">
        <canvas class="my-canvas"></canvas>
        <div class="my-music-btn rotate"> </div>
    </div>
    <script>
        // navigator.mediaDevices.getDisplayMedia({ audio: true })
        let ctx
        let source
        let analyser
        let musicFile   //上传文件转换的URL地址
        let musicPath    //默认音乐
        let fastInit = false    //  是否完成了初始化
        let audioBufferSourceNode = null;
        let theAnimationFrameID
        let theAnimationFrame = false  //true表示正在画
        const muiscBtn = document.querySelector(".my-music-btn");
        const theCanvas = document.querySelector(".my-canvas");
        const theMusic = document.querySelector('input')
        const musicPlay = document.createElement("audio");

        fetch("./偏爱.mp3").then(response => response.blob()).then(blob => {
            console.log(blob);
            musicPath = URL.createObjectURL(blob)
        })
        let theinit = () => {
            musicPath ? init() : fetch("./偏爱.mp3").then(response => response.blob()).then(blob => {
                console.log(blob);
                musicPath = URL.createObjectURL(blob)
            })

        }
        let randomData = Uint8Array.from(new Uint8Array(120), (v, k) => k);
        randomData.sort(() => Math.random() - 0.5);

        function init() {   //初始化
            ctx = new window.AudioContext();
            source = ctx.createMediaElementSource(musicPlay);
            analyser = ctx.createAnalyser();
            analyser.fftSize = 512;
            musicPlay.loop = true
            toPlay()
        }

        function toPlay() {
            musicPlay.src = musicFile || musicPath
            console.log(musicPlay.src);
            source.connect(analyser);
            source.connect(ctx.destination);
            draw()
            fastInit = true
            theinit = () => { return false }
        }
        // toPlay()


        muiscBtn.addEventListener("click", async () => {
            await theinit()
            // 检查 elem 是否包含 'my-class' 类名
            if (muiscBtn.classList.contains('rotate')) {
                // audioBufferSourceNode.start(0);
                muiscBtn.classList.remove("rotate");
                if (audioBufferSourceNode == null) {
                    musicPlay.play();
                }
            } else {
                if (audioBufferSourceNode == null) {
                    musicPlay.pause();
                }
                // 
                // audioBufferSourceNode.stop();
                muiscBtn.classList.add("rotate")
            }
        });

        //上传文件播放
        theMusic.addEventListener('change', async function (e) {
            const file = e.target.files[0]
            if (file) {
                musicFile = URL.createObjectURL(file)
                // await theinit()
                // toPlay()
                if (fastInit) { toPlay(); console.log('运行了'); }
            }
            muiscBtn.classList.contains('rotate') ? () => {
                muiscBtn.classList.remove("rotate");
                musicPlay.play();
            } : muiscBtn.classList.add("rotate")
        })

        function draw() {
            theAnimationFrameID = requestAnimationFrame(draw)
            const dataArray = new Uint8Array(analyser.frequencyBinCount);   // Uint8Array 的长度应该和 frequencyBinCount 相等
            analyser.getByteFrequencyData(dataArray)    // 调用 getByteFrequencyData 方法填充 Uint8Array

            theCanvas.width = 400;
            theCanvas.height = 400;
            let _ctx = theCanvas.getContext("2d");
            let byteFrequencyData = new Uint8Array(120).fill(0);
            byteFrequencyData = dataArray.slice(0, 120)

            const bData = [];
            randomData.forEach(value => {
                bData.push(byteFrequencyData[value]);
            })
            // console.log(bData);


            const angle = Math.PI * 2 / bData.length;
            _ctx.clearRect(0, 0, theCanvas.width, theCanvas.height);
            // _ctx.fillStyle = effectColor;
            _ctx.fillStyle = "#FA8C2A";
            _ctx.save();
            _ctx.translate(theCanvas.width / 2, theCanvas.height / 2);
            bData.forEach((value, index) => {
                _ctx.save();
                _ctx.rotate(angle * index);
                _ctx.beginPath();
                const h = value / 256 * 60;
                _ctx.roundRect(-4, 140, 4, (h < 4) ? 4 : h, 4);
                // 若上行的 roundRect 存在兼容性问题可以更换为下面注释的代码
                // this._ctx.fillRect(-4, 140,  4, (h < 4) ? 4 : h);
                _ctx.fill();
                _ctx.restore();
            });
            _ctx.restore();
        }



    </script>
</body>

</html>